package com.koron.css2.newProjectCenter.callback;

import com.github.pagehelper.PageInfo;
import com.koron.css2.baseConfig.mapper.PubReceiptMapper;
import com.koron.css2.clientCenter.Enum.ProcessStateEnum;
import com.koron.css2.clientCenter.bean.CtmInfoBean;
import com.koron.css2.clientCenter.mapper.CtmInfoMapper;
import com.koron.css2.newProjectCenter.Enum.PjCollectionPaymentStatus;
import com.koron.css2.newProjectCenter.bean.PjCollection;
import com.koron.css2.newProjectCenter.bean.PjInfoBean;
import com.koron.css2.newProjectCenter.bean.PjSettlement;
import com.koron.css2.newProjectCenter.bean.query.PjCollectionQuery;
import com.koron.css2.newProjectCenter.bean.query.PjSettlementQuery;
import com.koron.css2.newProjectCenter.impl.PjCollectionCountMoney;
import com.koron.css2.newProjectCenter.mapper.PjCollectionMapper;
import com.koron.css2.newProjectCenter.mapper.PjInfoMapper;
import com.koron.css2.newProjectCenter.mapper.PjSettlementMapper;
import com.koron.css2.newProjectCenter.service.PjInfoService;
import com.koron.css2.serviceManage.bean.RequestBean;
import com.koron.css2.serviceManage.bean.UserInfoBean;
import com.koron.css2.systemManage.bean.OrgUserBean;
import com.koron.css2.systemManage.mapper.OrgUserMapper;
import com.koron.css2.workflow.ProcessCommit;
import com.koron.css2.workflow.ProcessInterface;
import com.koron.css2.workflow.WorkflowImpl;
import com.koron.css2.workflow.bean.ProcessListBean;
import com.koron.css2.workflow.bean.ProcessListQueryBean;
import com.koron.util.Constant;
import com.koron.util.NumberUtils;
import com.koron.util.Tools;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.swan.bean.MessageBean;

import java.math.BigDecimal;
import java.util.*;

/**
 * 工程报装-编制结算-工作流回调接口
 *
 * @author 朱超
 * @since 2022-03-28 10:44:39
 */
public class PjSettlementCallback implements ProcessInterface {
    @Override
    public MessageBean<?> before(SessionFactory factory, UserInfoBean userInfo, String billId, String fromNodeCode, int operation) {
        try {
            PjSettlementMapper pjSettlementMapper = factory.getMapper(PjSettlementMapper.class);
            PjInfoMapper pjInfoMapper = factory.getMapper(PjInfoMapper.class);

            if (operation == OPERATION_AGREE && fromNodeCode.equals(ProcessStateEnum.PROCESSING.getState())) {
                // 1. 查询对应的编制结算单
                PjSettlementQuery pjSettlementQuery = new PjSettlementQuery();
                pjSettlementQuery.setId(billId);
                PjSettlement pjSettlement = pjSettlementMapper.getSingle(pjSettlementQuery);
                // 2. 更新结算标志
                pjInfoMapper.updateSettlementFlagById(pjSettlement.getConsultId());
                // 3. 新增工程收款数据
                PjInfoBean pjInfoBean = pjInfoMapper.selectById(pjSettlement.getConsultId());
                String projectCode = pjInfoBean.getBillNo();
                // 3.2 计算预缴金额（工程收款之和）
                PjCollectionMapper pjCollectionMapper = factory.getMapper(PjCollectionMapper.class);
                PjCollectionQuery pjCollectionQuery = new PjCollectionQuery();
                pjCollectionQuery.setProjectCode(projectCode);
                BigDecimal collectionMoney = PjCollectionCountMoney.getTotalMoney(pjCollectionMapper,pjInfoMapper,pjCollectionQuery);
                // 3.2 计算合计金额: 表前人工费结算+表后人工费结算+表前材料费结算+表后材料费结算+预算费结算+设计费结算+总管分摊费用
                BigDecimal totalMoney = new BigDecimal(0);
                // 表前人工费结算
                BigDecimal settlementLaborMeterBefore = pjSettlement.getSettlementLaborMeterBefore();
                // 表后人工费结算
                BigDecimal settlementLaborMeterAfter = pjSettlement.getSettlementLaborMeterAfter();
                // 表前材料费结算
                BigDecimal settlementMatrMeterBefore = pjSettlement.getSettlementMatrMeterBefore();
                // 表后材料费结算
                BigDecimal settlementMatrMeterAfter = pjSettlement.getSettlementMatrMeterAfter();
                // 预算费结算
                BigDecimal settlementCost = pjSettlement.getSettlementCost();
                // 设计费结算
                BigDecimal settlementDesignCost = pjSettlement.getSettlementDesignCost();
                // 总管分摊费用
                BigDecimal costShare = pjSettlement.getCostShare();
                totalMoney = totalMoney.add(settlementLaborMeterBefore);
                totalMoney = totalMoney.add(settlementLaborMeterAfter);
                totalMoney = totalMoney.add(settlementMatrMeterBefore);
                totalMoney = totalMoney.add(settlementMatrMeterAfter);
                totalMoney = totalMoney.add(settlementCost);
                totalMoney = totalMoney.add(settlementDesignCost);
                totalMoney = totalMoney.add(costShare);
                // 红线内费用
                totalMoney = totalMoney.add(new BigDecimal(pjSettlement.getRedLineInMoney() == null ? 0 : pjSettlement.getRedLineInMoney()));
                // 红线外费用
                totalMoney = totalMoney.add(new BigDecimal(pjSettlement.getRedLineOutMoney() == null ? 0 : pjSettlement.getRedLineOutMoney()));
                // 器具费用
                totalMoney = totalMoney.add(new BigDecimal(pjSettlement.getUtensilMoney() == null ? 0 : pjSettlement.getUtensilMoney()));
                if(totalMoney.compareTo(collectionMoney) == 0) {
                    return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "编制结算提交成功", null);
                } else { // 3.4 合计金额 != 预缴金额
                    PjCollection pjCollection = new PjCollection();
                    CtmInfoMapper ctmInfoMapper = factory.getMapper(CtmInfoMapper.class);
                    Map<String,String> PPT = Tools.mapDicByCode(factory,"PPT");
                    // 3.4.1 clientName
                    CtmInfoBean ctmInfoBean = ctmInfoMapper.getCtmInfoById(pjInfoBean.getUserCtmTempId(),CtmInfoBean.CTMTEMP);
                    pjCollection.setClientName(ctmInfoBean.getCtmName());
                    // 3.4.2 constructionUnit
                    pjCollection.setConstructionUnit(pjInfoBean.getConstructionUnit());
                    // 3.4.3 projectAddress
                    pjCollection.setProjectAddress(pjInfoBean.getInstallAddr());
                    // 3.4.5 projectCode
                    pjCollection.setProjectCode(projectCode);
                    // 3.4.5 projectDate
                    pjCollection.setProjectDate(pjInfoBean.getBillDate());
                    // 3.5.6 projectName
                    pjCollection.setProjectName(pjInfoBean.getPjName());
                    pjCollection.setPjId(pjInfoBean.getId());
                    // 3.5 合计金额 > 预缴金额
                    if (totalMoney.compareTo(collectionMoney) == 1) {
                        BigDecimal money = totalMoney.subtract(collectionMoney);
                        pjCollection.setMoney(money);
                        pjCollection.setNotes("补缴金额 " + money);
                        // 3.5.1 结算收款
                        pjCollection.setType(3);
                    }
                    // 3.6 合计金额 < 预缴金额
                    if (totalMoney.compareTo(collectionMoney) == -1) {
                        BigDecimal money = totalMoney.subtract(collectionMoney);
                        pjCollection.setMoney(money);
                        pjCollection.setNotes("退款金额 " + money);
                        // 3.6.1 结算退款
                        pjCollection.setType(4);
                    }
                    // 3.7 id,tenantId,createTime,createName,createAccount
                    pjCollection.setCreateInfo(userInfo);
                    // 3.8 status
                    pjCollection.setStatus(PjCollectionPaymentStatus.BEFORECOLLECTION.getStatus());
                    // 3.9 新增工程收款数据
                    pjCollectionMapper.insert(pjCollection);
                }

                // 表前材料费结算
                pjInfoBean.setSetmtMatrMeterBefore(settlementMatrMeterBefore.doubleValue());
                // 表前人工费结算
                pjInfoBean.setSetmtLaborMeterBefore(settlementLaborMeterBefore.doubleValue());
                // 表后材料费结算
                pjInfoBean.setSetmtMatrMeterAfter(settlementMatrMeterAfter.doubleValue());
                // 表后人工费结算
                pjInfoBean.setSetmtLaborMeterAfter(settlementLaborMeterAfter.doubleValue());
                // 预算费结算
                pjInfoBean.setSetmtBudgetCost(settlementCost.doubleValue());
                // 设计费结算
                pjInfoBean.setSetmtDesignCost(settlementDesignCost.doubleValue());
                // 红线内费用
                pjInfoBean.setRedLineInMoney(pjSettlement.getRedLineInMoney());
                // 红线外费用
                pjInfoBean.setRedLineOutMoney(pjSettlement.getRedLineOutMoney());
                // 器具费用
                pjInfoBean.setUtensilMoney(pjSettlement.getUtensilMoney());
                // 工程造价
                pjInfoBean.setCostShare(costShare.doubleValue());
                // 结算日期
                pjInfoBean.setSetmtDate(new Date());
                // 结算合计金额
                pjInfoBean.setSetmtMoney(totalMoney.doubleValue());
                // 退补金额
                pjInfoBean.setBackFillMoney(NumberUtils.subtract(totalMoney.doubleValue(), collectionMoney.doubleValue()));
                pjInfoBean.setUpdateInfo(userInfo);
                // 同步保存至工程主表的结算字段
                pjInfoMapper.savePreSetmt(pjInfoBean);
                
                // 如果工程主流程处于 工程结算以及工程收款节点需要自动跳过
                if (Objects.equals(PjInfoService.PJSETTLEMENT, pjInfoBean.getProcessState()) || Objects.equals(PjInfoService.PJPAYMENT, pjInfoBean.getProcessState())) {
                    processCommit(factory, pjSettlement.getConsultId(), userInfo);
                }
            }
            return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "编制结算提交成功", null);
        } catch (Exception e) {
            logger.error("编制结算提交失败",e);
        }
        return MessageBean.create(Constant.MESSAGE_INT_FAIL, "编制结算提交失败", null);
    }

    @Override
    public MessageBean<?> after(SessionFactory factory, UserInfoBean userInfo, String billId, String fromNodeCode, String toNodeCode) {
        return null;
    }

    /**
     * @param factory 数据源
     * @param pjId 工程主键ID
     * @param userInfo 当前登录人信息
     */
    private void processCommit(SessionFactory factory, String pjId, UserInfoBean userInfo){
        String operator = "";
        PjInfoMapper pjInfoMapper = factory.getMapper(PjInfoMapper.class);
        PjInfoBean pjInfoBean = pjInfoMapper.selectById(pjId);
        // 递归退出
        if (!Objects.equals(PjInfoService.PJSETTLEMENT, pjInfoBean.getProcessState()) && !Objects.equals(PjInfoService.PJPAYMENT, pjInfoBean.getProcessState())){
            return;
        }
        if (StringUtils.isNotEmpty(pjInfoBean.getProcessHandleMan())){
            String processHandleMan = pjInfoBean.getProcessHandleMan();
            String[] processHandleManArray = processHandleMan.split(",");
            OrgUserMapper orgUserMapper = factory.getMapper(OrgUserMapper.class);
            OrgUserBean orgUser = orgUserMapper.selectByName(processHandleManArray[0]);
            operator = orgUser.getCode();
        }
        PubReceiptMapper pubReceiptMapper = factory.getMapper(PubReceiptMapper.class);
        String setCode = pubReceiptMapper.getWorkflowApp(userInfo.getCurWaterCode());
        ProcessListQueryBean processListQueryBean = new ProcessListQueryBean();
        processListQueryBean.setType(2);
        processListQueryBean.setStatus(1);
        processListQueryBean.setSetCode(setCode);
        processListQueryBean.setBillId(pjId);
        PageInfo<ProcessListBean> page = WorkflowImpl.workflow(processListQueryBean);
        List<ProcessListBean> processListBeanList = page.getList();
        if (processListBeanList != null && processListBeanList.size() > 0) {
            Map<String, String> processCommitMap = new HashMap<>();
            processCommitMap.put("taskId", processListBeanList.get(0).getCurTaskId());
            // 4.3 receiptType
            processCommitMap.put("receiptType", "pj_info_new#" + pjInfoBean.getPjType());
            // 4.4 operation
            processCommitMap.put("operation", ProcessInterface.OPERATION_AGREE + "");
            // 4.5 operator
            processCommitMap.put("operator", operator);
            // 4.6 setCode
            processCommitMap.put("setCode", setCode);
            // 单据主键ID
            processCommitMap.put("billId", pjId);
            processCommitMap.put("comment", "系统自动通过");

            RequestBean request = new RequestBean();
            request.setData(processCommitMap);
            ProcessCommit processCommit = new ProcessCommit();
            MessageBean message = processCommit.exec(factory, userInfo, request);
            if (message.getCode() != Constant.MESSAGE_INT_SUCCESS){
                throw new RuntimeException("【工程结算】【工程收款】节点自动跳转流程提交失败," + message.getDescription());
            }
        }
        processCommit(factory, pjId, userInfo);
    }
}
